-- minimap default position - you can move it ingame by holding down ALT!
position = "TOPRIGHT"     	
position_x = -35          		
position_y = -35         		

-- quest tracker position
qparent = UIParent         
qanchor = "TOPRIGHT"  	 
qposition_x = -60           
qposition_y = -260         
qheight = 400             

local scale = 1.0

local useInfoPanel = false		-- enable disable fps/latency and clock
local showclock = false			-- ONLY show clock - makes sense to set useInfoPanel to false if you only want to show the clock ^^
local AddonNumb = 20			-- maximum number of addons shown in tooltip (will always show set number of top memory usage addons)

local mediaFolder = "Interface\\AddOns\\dMinimap\\media\\"	-- don't touch this ...
local texture = "Interface\\Buttons\\WHITE8x8"
local backdrop = {bgFile = texture, edgeFile = texture, edgeSize = 1, insets = { left = -1, right = -1, top = -1, bottom = -1}}

local mailicon = mediaFolder.."mail"
local font = mediaFolder.."Pixelway_Baseline.ttf"
local fontSize = 10
local fontFlag = "OUTLINE MONOCHROME"			-- "THINOUTLINE", "OUTLINE MONOCHROME", "OUTLINE" or nil (no outline)

local backdropcolor = {26/255, 25/255, 31/255}			-- backdrop color	
local brdcolor = {65/255, 74/255, 79/255}				-- backdrop border color
local infocolor = {29/255, 63/255, 72/255}				-- info panel color

local classColoredBorder = false						-- color border by class

-----------
-- style --
-----------
local _, class = UnitClass('player')
local color = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[class] or RAID_CLASS_COLORS[class]			

Minimap:SetMaskTexture(texture)
Minimap:SetFrameStrata("BACKGROUND")
Minimap:ClearAllPoints()
Minimap:SetPoint(position, UIParent, position_x, position_y)
Minimap:SetScale(scale)

LFDSearchStatus:SetClampedToScreen(true)

BorderFrame = CreateFrame("Frame", nil, Minimap)
BorderFrame:SetPoint("TOPLEFT", Minimap, "TOPLEFT", -2, 2)
BorderFrame:SetPoint("BOTTOMRIGHT", Minimap, "BOTTOMRIGHT", 2, -2)	
BorderFrame:SetBackdrop(backdrop)
if not classColoredBorder then
	BorderFrame:SetBackdropBorderColor(unpack(brdcolor))
else
	BorderFrame:SetBackdropBorderColor(color.r, color.g, color.b)
end	
BorderFrame:SetBackdropColor(unpack(backdropcolor))
BorderFrame:SetFrameLevel(0)		

------------------------
-- fps latency memory --
------------------------
if useInfoPanel then	

local FLMframe = CreateFrame("Button", "FLMframe", Minimap)
FLMframe:SetPoint("TOP", Minimap, "BOTTOM", 0, -1)
FLMframe:SetSize(Minimap:GetWidth()+4, fontSize+6)
FLMframe:SetFrameLevel(0)
FLMframe:SetBackdrop(backdrop)
if not classColoredBorder then
	FLMframe:SetBackdropBorderColor(unpack(brdcolor))
else
	FLMframe:SetBackdropBorderColor(color.r, color.g, color.b)
end	
FLMframe:SetBackdropColor(unpack(backdropcolor))

local FLMframeT = FLMframe:CreateTexture(nil, "ARTWORK")
FLMframeT:SetPoint("TOPLEFT", FLMframe, "TOPLEFT", 2, -2)
FLMframeT:SetPoint("BOTTOMRIGHT", FLMframe, "BOTTOMRIGHT", -2, 2)	
FLMframeT:SetTexture(mediaFolder.."dO")
FLMframeT:SetVertexColor(unpack(infocolor))

local text = FLMframe:CreateFontString(nil, "OVERLAY")
text:SetPoint("CENTER", FLMframe, 4, 0)
text:SetFont(font, fontSize, fontFlag)
--text:SetShadowOffset(1, -1)
text:SetTextColor(color.r, color.g, color.b)
	
    --========[ important functions ]========--
local function Addoncompare(a, b)
    return a.memory > b.memory
end

local function MemFormat(v)
    if (v > 1024) then
        return string.format("%.2f MiB", v / 1024)
    else
        return string.format("%.2f KiB", v)
    end
end

local function ColorGradient(perc, ...)
	if (perc > 1) then
		local r, g, b = select(select('#', ...) - 2, ...)
		return r, g, b
	elseif (perc < 0) then
		local r, g, b = ...
		return r, g, b
	end
	
	local num = select('#', ...) / 3

	local segment, relperc = math.modf(perc*(num-1))
	local r1, g1, b1, r2, g2, b2 = select((segment*3)+1, ...)

	return r1 + (r2-r1)*relperc, g1 + (g2-g1)*relperc, b1 + (b2-b1)*relperc
end

local function TimeFormat(time)
	local t = format("%.1ds",floor(mod(time,60)))
	if (time > 60) then
		time = floor(time / 60)
		t = format("%.1dm ",mod(time,60))..t
		if (time > 60) then
			time = floor(time / 60)
			t = format("%.1dh ",mod(time,24))..t
			if (time > 24) then
				time = floor(time / 24)
				t = format("%dd ",time)..t
			end
		end
	end
	return t
end

local function ColorizeLatency(v)
    if (v < 100) then
        return {r = 0, g = 1, b = 0}
    elseif (v < 300) then
        return {r = 1, g = 1, b = 0}
    else
        return {r = 1, g = 0, b = 0}
    end
end

local function ColorizeFramerate(v)
    if (v < 10) then
        return {r = 1, g = 0, b = 0}
    elseif (v < 30) then
        return {r = 1, g = 1, b = 0}
    else
        return {r = 0, g = 1, b = 0}
    end
end
	
    --========[ update ]========--
local lastUpdate = 0
local updateDelay = 1
FLMframe:SetScript("OnUpdate", function(self, elapsed)
    lastUpdate = lastUpdate + elapsed
    if (lastUpdate > updateDelay) then
        lastUpdate = 0
		local time = date("|c00ffffff%H|r:|c00ffffff%M|r")
		fps = GetFramerate()
		fps = "|c00ffffff"..floor(fps+0.5).."|r fps   "
		lag = select(3, GetNetStats())
		lag = "|c00ffffff"..lag.."|r ms   "
        text:SetText(lag..fps..time)
    end
end)

FLMframe:SetScript("OnEnter", function()
    GameTooltip:SetOwner(FLMframe)
    collectgarbage()
    local memory, i, addons, total, entry, total
    local latencycolor = ColorizeLatency(select(3, GetNetStats()))
    local fpscolor = ColorizeFramerate(GetFramerate())
        
    GameTooltip:AddLine(date("%A, %d %B, %Y"), 1, 1, 1)
    GameTooltip:AddDoubleLine("Framerate:", format("%.1f fps", GetFramerate()), color.r, color.g, color.b, fpscolor.r, fpscolor.g, fpscolor.b)
    GameTooltip:AddDoubleLine("Latency:", format("%d ms", select(3, GetNetStats())), color.r, color.g, color.b, latencycolor.r, latencycolor.g, latencycolor.b)
    GameTooltip:AddDoubleLine("System Uptime:", TimeFormat(GetTime()), color.r, color.g, color.b, 1, 1, 1)
 	GameTooltip:AddDoubleLine(". . . . . . . . . . .", ". . . . . . . . . . .", 1, 1, 1, 1, 1, 1)
	
    addons = {}
    total = 0
    UpdateAddOnMemoryUsage()
    for i = 1, GetNumAddOns(), 1 do
        if GetAddOnMemoryUsage(i) > 0 then
            memory = GetAddOnMemoryUsage(i)
            entry = {name = GetAddOnInfo(i), memory = memory}
            table.insert(addons, entry)
            total = total + memory
        end
    end
	
	table.sort(addons, Addoncompare)

	i = 0
	for _,entry in pairs(addons) do
		local cr, cg, cb = ColorGradient((entry.memory / 800), 0, 1, 0, 1, 1, 0, 1, 0, 0)
		GameTooltip:AddDoubleLine(entry.name, MemFormat(entry.memory), 1, 1, 1, cr, cg, cb)
	
		i = i + 1
		if i >= AddonNumb then
			break
		end		
	end
	
    local cr, cg, cb = ColorGradient((entry.memory / 800), 0, 1, 0, 1, 1, 0, 1, 0, 0) 
    GameTooltip:AddDoubleLine(". . . . . . . . . . .", ". . . . . . . . . . .", 1, 1, 1, 1, 1, 1)
    GameTooltip:AddDoubleLine("Total", MemFormat(total), color.r, color.g, color.b, cr, cg, cb)
    GameTooltip:AddDoubleLine("..with Blizzard", MemFormat(collectgarbage("count")), color.r, color.g, color.b, cr, cg, cb)
    GameTooltip:Show()
end)

FLMframe:SetScript("OnLeave", function() 
    GameTooltip:Hide() 
end)

    --========[ mem cleanup ]========--
FLMframe:SetScript("OnClick", function()
    if (not IsAltKeyDown()) then
        UpdateAddOnMemoryUsage()
        local memBefore = gcinfo()
        collectgarbage()
        UpdateAddOnMemoryUsage()
        local memAfter = gcinfo()
        DEFAULT_CHAT_FRAME:AddMessage("Memory cleaned: |cff00FF00"..MemFormat(memBefore - memAfter))
    end
end)
	
end
	
---------------------
-- hide some stuff --
---------------------
MinimapBorder:Hide()
MinimapBorderTop:Hide()
MinimapZoomIn:Hide()
MinimapZoomOut:Hide()
MiniMapVoiceChatFrame:Hide()
GameTimeFrame:Hide()
MinimapZoneTextButton:Hide()
MiniMapTracking:Hide()
MiniMapMailBorder:Hide()
MinimapNorthTag:SetAlpha(0)
MiniMapInstanceDifficulty:SetAlpha(0)
GuildInstanceDifficulty:SetAlpha(0)

if showclock then
	LoadAddOn('Blizzard_TimeManager')
	local clockFrame, clockTime = TimeManagerClockButton:GetRegions()
	clockFrame:Hide()
	clockTime:Show()
	clockTime:SetFont(font, fontSize, fontFlag)
	TimeManagerClockButton:SetPoint("BOTTOM", Minimap, 0, -6)
else
	LoadAddOn('Blizzard_TimeManager')
	TimeManagerClockButton:Hide()	
end

---------------------
-- move some stuff --
---------------------
WatchFrame:ClearAllPoints()	
WatchFrame.ClearAllPoints = function() end
WatchFrame:SetPoint(qanchor, qparent, qanchor, qposition_x, qposition_y)
WatchFrame.SetPoint = function() end
WatchFrame:SetClampedToScreen(true)
WatchFrame:SetHeight(qheight)

MiniMapMailFrame:ClearAllPoints()
MiniMapMailFrame:SetPoint("TOPRIGHT", Minimap, 4, 4)
MiniMapMailIcon:SetTexture(mailicon)

MiniMapBattlefieldFrame:ClearAllPoints()
MiniMapBattlefieldFrame:SetPoint("BOTTOMRIGHT", Minimap, 4, 0)
MiniMapBattlefieldFrame:SetFrameLevel(4)
MiniMapBattlefieldBorder:Hide()
MiniMapWorldMapButton:Hide()
MiniMapInstanceDifficulty:ClearAllPoints()
MiniMapInstanceDifficulty:SetParent(Minimap)
MiniMapInstanceDifficulty:SetPoint("TOPLEFT", Minimap, "TOPLEFT", 0, 0)
function UpdateLFG()
	MiniMapLFGFrame:ClearAllPoints()
	MiniMapLFGFrame:SetPoint("BOTTOMLEFT", Minimap, "BOTTOMLEFT", 2, 2)
    LFDSearchStatus:ClearAllPoints()
    LFDSearchStatus:SetPoint(position, MiniMapLFGFrame, position)
end
MiniMapLFGFrameBorder:SetAlpha(0)
DropDownList1:SetClampedToScreen(true)
hooksecurefunc("MiniMapLFG_UpdateIsShown", UpdateLFG)

---------------------
-- mousewheel zoom --
---------------------
Minimap:EnableMouseWheel(true)
Minimap:SetScript("OnMouseWheel", function(self, z)
	local c = Minimap:GetZoom()
	if(z > 0 and c < 5) then
		Minimap:SetZoom(c + 1)
	elseif(z < 0 and c > 0) then
		Minimap:SetZoom(c - 1)
	end
end)

------------------------
-- move and clickable --
------------------------
Minimap:SetMovable(true)
Minimap:SetUserPlaced(true)
Minimap:SetScript("OnMouseDown", function()
    if (IsAltKeyDown()) then
        Minimap:ClearAllPoints()
        Minimap:StartMoving()
    end
end)

Minimap:SetScript('OnMouseUp', function(self, button)
Minimap:StopMovingOrSizing()
    if (button == 'RightButton') then
        ToggleDropDownMenu(1, nil, MiniMapTrackingDropDown, self, - (Minimap:GetWidth() * 0.7), -3)
    elseif (button == 'MiddleButton') then
        ToggleCalendar()
    else
        Minimap_OnClick(self)
    end
end)

-- calendar slashcmd
SlashCmdList["CALENDAR"] = function()
	ToggleCalendar()
end
SLASH_CALENDAR1 = "/cl"
SLASH_CALENDAR2 = "/calendar"

function GetMinimapShape() return 'SQUARE' end